package com.yeyks.appcontroller;

import com.alibaba.fastjson.JSONObject;
import com.yeyks.base.Arguments;
import com.yeyks.constant.ConfigKey;
import com.yeyks.constant.MessageTemplate;
import com.yeyks.dal.domain.*;
import com.yeyks.dto.OrderDetailDTO;
import com.yeyks.dto.OrderInfoDTO;
import com.yeyks.exception.ServiceException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.OrderStatus;
import com.yeyks.model.PreOrderType;
import com.yeyks.model.em.VipOrderStatus;
import com.yeyks.model.enums.FishBallEnum;
import com.yeyks.service.*;
import com.yeyks.util.*;
import com.yeyks.wxpay.impl.MyConfig;
import com.yeyks.service.ConfigService;
import com.yeyks.service.HotelService;
import com.yeyks.service.OrderService;
import com.yeyks.service.PayService;
import com.yeyks.util.TextValidator;
import com.yeyks.util.Utility;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @Author fuchangshuai
 * @date 2019/3/26 4:27 PM
 */
@Api(tags = "订单接口", description = "订单")
@Slf4j
@RestController("appOrderInfoController")
@RequestMapping(value = "/app/order")
public class OrderInfoController {
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private PayService payService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private HotelService hotelService;
    @Autowired
    private VipOrderService vipOrderService;
    @Autowired
    private RoomInfoService roomInfoService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private MessageNoticeTemplateService templateService;
    @Autowired
    private MessageNoticeService noticeService;
    @Autowired
    private FishBallService fishBallService;

    /**
     * 查询各状态的订单数
     *
     * @param token
     * @param pageNum
     * @param pageSize
     * @param type     默认1全部，2已付款，3未支付，4已取消
     * @return
     */
    @ApiOperation(value = "查询各状态的订单数", notes = "查询各状态的订单数")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "pageNum", value = "当前页", defaultValue = "1", dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "pageSize", value = "每页个数", defaultValue = "10", dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "type", value = "默认1全部，2已付款，3未支付，4已取消", defaultValue = "1", dataType = "int")
    })
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public ResponseEntity<?> list(@RequestParam(name = "token") String token,
                                  @RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
                                  @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                  @RequestParam(name = "type", defaultValue = "1") Integer type
    ) {
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        List<OrderInfoDTO> orderInfos = orderService.selectOrderList(userInfo.getId(), pageNum, pageSize, type);
        return ResponseEntity.ok(AjaxResponseBody.success(orderInfos));
    }

    /**
     * 用户删除订单
     *
     * @param token
     * @param orderNo
     * @return
     */
    @ApiOperation(value = "用户删除订单", notes = "用户删除订单")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "orderNo", value = "订单号", required = true, dataType = "String")
    })
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public ResponseEntity<?> orderDelete(@RequestParam(name = "token") String token,
                                         @RequestParam(name = "orderNo") String orderNo) {
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        checkParamOrderNo(orderNo);
        OrderInfo orderInfo = orderService.selectOrderByOrderNo(orderNo);
        if (orderInfo == null) {
            throw new ServiceException("该订单号不存在");
        }
        if (!orderInfo.getUserId().equals(userInfo.getId())) {
            throw new ServiceException("非本人订单");
        }
        Integer res = orderService.updateOrderDelStatus(orderNo, 1);
        if (res != 1) {
            log.info("更新删除状态失败");
        }
        return ResponseEntity.ok(AjaxResponseBody.success());
    }

    /**
     * 用户确认订单（生成订单并返回给客户端相应参数）
     *
     * @param token
     * @param checkInDate  入住时间
     * @param checkOutDate 离开时间
     * @param count        预定的房间间数
     * @param remark       备注
     * @param couponId     券id
     * @param name         下单用户真实姓名
     * @param phone        下单用户手机号
     * @return
     */
    @ApiOperation(value = "用户确认订单")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "checkInDate", value = "入住时间", required = true, dataType = "Long"),
            @ApiImplicitParam(paramType = "query", name = "checkOutDate", value = "离开时间", required = true, dataType = "Long"),
            @ApiImplicitParam(paramType = "query", name = "count", value = "预定的房间数", defaultValue = "1", dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "remark", value = "备注", dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "couponId", value = "券id", defaultValue = "0", dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "roomId", value = "房间id", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "type", value = "付款类型(wxpay,alipay)", dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "name", value = "下单用户真实姓名", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "phone", value = "下单用户手机号", required = true, dataType = "String")
    })
    @RequestMapping(value = "/preOrder", method = RequestMethod.POST)
    public ResponseEntity<?> preOrder(@RequestParam(name = "token") String token,
                                      @RequestParam(name = "checkInDate") Long checkInDate,
                                      @RequestParam(name = "checkOutDate") Long checkOutDate,
                                      @RequestParam(name = "count", defaultValue = "1") Integer count,
                                      @RequestParam(name = "remark", required = false) String remark,
                                      @RequestParam(name = "couponId", defaultValue = "0") Integer couponId,
                                      @RequestParam(name = "roomId") Integer roomId,
                                      @RequestParam(name = "type") String type,
                                      @RequestParam(name = "name") String name,
                                      @RequestParam(name = "phone") String phone,
                                      HttpServletRequest request) {

        OrderInfo param = getOrderInfo(name, phone);
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        String ip = Utility.getRemoteIP(request);
        Map<String, String> map = orderService.preOrder(userInfo, param, checkInDate, checkOutDate, count, remark, couponId, roomId, type, ip);
        return ResponseEntity.ok(AjaxResponseBody.success(map));
    }

    /**
     * 用户确认订单（生成订单并返回给客户端相应参数）
     *
     * @param token
     * @param checkInDate  入住时间
     * @param checkOutDate 离开时间
     * @param count        预定的房间间数
     * @param remark       备注
     * @param couponId     券id
     * @param name         下单用户真实姓名
     * @param phone        下单用户手机号
     * @return
     */
    @ApiOperation(value = "用户确认订单(修改券id)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "checkInDate", value = "入住时间", required = true, dataType = "Long"),
            @ApiImplicitParam(paramType = "query", name = "checkOutDate", value = "离开时间", required = true, dataType = "Long"),
            @ApiImplicitParam(paramType = "query", name = "count", value = "预定的房间数", defaultValue = "1", dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "remark", value = "备注", dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "couponId", value = "用户券id", defaultValue = "0", dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "roomId", value = "房间id", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "type", value = "付款类型(wxpay,alipay)", dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "name", value = "下单用户真实姓名", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "phone", value = "下单用户手机号", required = true, dataType = "String")
    })
    @RequestMapping(value = "/preOrderV2", method = RequestMethod.POST)
    public ResponseEntity<?> preOrderV2(@RequestParam(name = "token") String token,
                                      @RequestParam(name = "checkInDate") Long checkInDate,
                                      @RequestParam(name = "checkOutDate") Long checkOutDate,
                                      @RequestParam(name = "count", defaultValue = "1") Integer count,
                                      @RequestParam(name = "remark", required = false) String remark,
                                      @RequestParam(name = "couponId", defaultValue = "0") Integer couponId,
                                      @RequestParam(name = "roomId") Integer roomId,
                                      @RequestParam(name = "type") String type,
                                      @RequestParam(name = "name") String name,
                                      @RequestParam(name = "phone") String phone,
                                      HttpServletRequest request) {

        OrderInfo param = getOrderInfo(name, phone);
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        String ip = Utility.getRemoteIP(request);
        Map<String, String> map = orderService.preOrderV2(userInfo, param, checkInDate, checkOutDate, count, remark, couponId, roomId, type, ip);
        return ResponseEntity.ok(AjaxResponseBody.success(map));
    }

    /**
     * h5用户确认订单
     *
     * @param token
     * @param checkInDate  入住时间
     * @param checkOutDate 离开时间
     * @param count        预定的房间间数
     * @param remark       备注
     * @param couponId     券id
     * @param name         下单用户真实姓名
     * @param phone        下单用户手机号
     * @return
     */
    @ApiOperation(value = "h5用户确认订单")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "checkInDate", value = "入住时间", required = true, dataType = "Long"),
            @ApiImplicitParam(paramType = "query", name = "checkOutDate", value = "离开时间", required = true, dataType = "Long"),
            @ApiImplicitParam(paramType = "query", name = "count", value = "预定的房间数", defaultValue = "1", dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "remark", value = "备注", dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "couponId", value = "券id", defaultValue = "0", dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "roomId", value = "房间id", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "name", value = "下单用户真实姓名", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "phone", value = "下单用户手机号", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "code", value = "用户code", dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "sourceType", value = "sourceType", defaultValue = "wx", dataType = "String")
    })
    @RequestMapping(value = "/h5/preOrder", method = RequestMethod.POST)
    public ResponseEntity<?> h5PreOrder(@RequestParam(name = "token") String token,
                                        @RequestParam(name = "checkInDate") Long checkInDate,
                                        @RequestParam(name = "checkOutDate") Long checkOutDate,
                                        @RequestParam(name = "count", defaultValue = "1") Integer count,
                                        @RequestParam(name = "remark", required = false) String remark,
                                        @RequestParam(name = "couponId", defaultValue = "0") Integer couponId,
                                        @RequestParam(name = "roomId") Integer roomId,
                                        @RequestParam(name = "name") String name,
                                        @RequestParam(name = "phone") String phone,
                                        @RequestParam(name = "code", required = false) String code,
                                        @RequestParam(name = "sourceType", defaultValue = "wx") String sourceType,
                                        HttpServletRequest request) {
        OrderInfo param = getOrderInfo(name, phone);
        int orderType = PreOrderType.parse(sourceType);
        //true代表是公众号，false代表小程序
        boolean flag = orderType == PreOrderType.wx || orderType == PreOrderType.h5;
        String type = "xcx";
        if (flag) {
            type = "gzh";
        }
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        //检测是否该用户是否有openid
        String openId = checkOpenid(userInfo, code, flag);
//        String openId = alwayGetOpenid(code, flag);
        String ip = Utility.getRemoteIP(request);
        Map<String, String> map = orderService.h5PreOrder(userInfo, param, checkInDate, checkOutDate, count, remark, couponId, roomId, type, ip, openId, flag);
        return ResponseEntity.ok(AjaxResponseBody.success(map));
    }

//    @ApiOperation(value = "h5用户确认订单")
//    @ApiImplicitParams({
//            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
//            @ApiImplicitParam(paramType = "query", name = "checkInDate", value = "入住时间", required = true, dataType = "Long"),
//            @ApiImplicitParam(paramType = "query", name = "checkOutDate", value = "离开时间", required = true, dataType = "Long"),
//            @ApiImplicitParam(paramType = "query", name = "count", value = "预定的房间数", defaultValue = "1", dataType = "int"),
//            @ApiImplicitParam(paramType = "query", name = "remark", value = "备注", dataType = "String"),
//            @ApiImplicitParam(paramType = "query", name = "couponId", value = "券id", defaultValue = "0", dataType = "int"),
//            @ApiImplicitParam(paramType = "query", name = "roomId", value = "房间id", required = true, dataType = "int"),
//            @ApiImplicitParam(paramType = "query", name = "name", value = "下单用户真实姓名", required = true, dataType = "String"),
//            @ApiImplicitParam(paramType = "query", name = "phone", value = "下单用户手机号", required = true, dataType = "String"),
//            @ApiImplicitParam(paramType = "query", name = "code", value = "用户code", dataType = "String"),
//            @ApiImplicitParam(paramType = "query", name = "sourceType", value = "sourceType", defaultValue = "wx", dataType = "String")
//    })
//    @RequestMapping(value = "/h5/preOrderV2", method = RequestMethod.POST)
//    public ResponseEntity<?> h5PreOrderV2(@RequestParam(name = "token") String token,
//                                        @RequestParam(name = "checkInDate") Long checkInDate,
//                                        @RequestParam(name = "checkOutDate") Long checkOutDate,
//                                        @RequestParam(name = "count", defaultValue = "1") Integer count,
//                                        @RequestParam(name = "remark") String remark,
//                                        @RequestParam(name = "couponId", defaultValue = "0") Integer couponId,
//                                        @RequestParam(name = "roomId") Integer roomId,
//                                        @RequestParam(name = "name") String name,
//                                        @RequestParam(name = "phone") String phone,
//                                        @RequestParam(name = "code", required = false) String code,
//                                        @RequestParam(name = "sourceType", defaultValue = "wx") String sourceType,
//                                        HttpServletRequest request) {
//        OrderInfo param = getOrderInfo(name, phone);
//        int orderType = PreOrderType.parse(sourceType);
//        //true代表是公众号，false代表小程序
//        boolean flag = orderType == PreOrderType.wx || orderType == PreOrderType.h5;
//        String type = "xcx";
//        if (flag) {
//            type = "gzh";
//        }
//        UserInfo userInfo = userInfoService.tokenUserInfo(token);
//        String openId = userInfoService.getOpenId(userInfo, code, type);
//        String ip = Utility.getRemoteIP(request);
//        Map<String, String> map = orderService.h5PreOrderV2(userInfo, param, checkInDate, checkOutDate, count, remark, couponId, roomId, type, ip, openId, flag);
//        return ResponseEntity.ok(AjaxResponseBody.success(map));
//    }

    /**
     * 用户去支付
     *
     * @param token
     * @param orderNo 订单号
     * @param type    支付方式
     * @return
     */
    @ApiOperation(value = "用户去支付", notes = "用户去支付")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "orderNo", value = "订单号", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "type", value = "支付类型（wxpay,alipay）", required = true, dataType = "String")
    })
    @RequestMapping(value = "/goPay", method = RequestMethod.POST)
    public ResponseEntity<?> goPay(@RequestParam(name = "token") String token,
                                   @RequestParam(name = "orderNo") String orderNo,
                                   @RequestParam(name = "type") String type,
                                   HttpServletRequest request) {
        checkParamOrderNo(orderNo);
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        String ip = Utility.getRemoteIP(request);
        Map<String, String> map = orderService.goPay(userInfo, orderNo, type, ip);
        return ResponseEntity.ok(AjaxResponseBody.success(map));
    }

    /**
     * h5用户去支付
     *
     * @param token
     * @param orderNo    订单号
     * @param code       code
     * @param sourceType
     * @return
     */
    @ApiOperation(value = "h5用户去支付", notes = "当获取不到openid时code必传")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "orderNo", value = "订单号", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "code", value = "code", dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "sourceType", value = "sourceType", defaultValue = "wx", dataType = "String")
    })
    @RequestMapping(value = "/h5/goPay", method = RequestMethod.POST)
    public ResponseEntity<?> h5GoPay(@RequestParam(name = "token") String token,
                                     @RequestParam(name = "orderNo") String orderNo,
                                     @RequestParam(name = "code", required = false) String code,
                                     @RequestParam(name = "sourceType", defaultValue = "wx") String sourceType,
                                     HttpServletRequest request) {
        checkParamOrderNo(orderNo);
        int orderType = PreOrderType.parse(sourceType);
        //true代表是公众号，false代表小程序
        boolean flag = orderType == PreOrderType.wx || orderType == PreOrderType.h5;
        String type = "xcx";
        if (flag) {
            type = "gzh";
        }
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        //检测是否该用户是否有openid
        String openId = checkOpenid(userInfo, code, flag);
//        String openId = alwayGetOpenid(code, flag);
        String ip = Utility.getRemoteIP(request);
        Map<String, String> map = orderService.h5GoPay(userInfo, orderNo, type, ip, openId, flag);
        return ResponseEntity.ok(AjaxResponseBody.success(map));
    }

    /**
     * 订单退款(用户申请退款，将订单修改为正在退款状态，并修改退款值)
     *
     * @return
     */
    @ApiOperation(value = "订单退款", notes = "订单退款")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "orderNo", value = "订单号", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "reason", value = "退款原因", required = true, dataType = "String")
    })
    @RequestMapping(value = "/refundOrder", method = RequestMethod.POST)
    public ResponseEntity<?> refundOrder(@RequestParam(name = "token") String token,
                                         @RequestParam(name = "orderNo") String orderNo,
                                         @RequestParam(name = "reason") String reason) {
        log.info("参数token和orderNo{}{}", token, orderNo);
        if (!Arguments.notEmpty(reason)) {
            throw new ServiceException("退款原因不能为空");
        }
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        //通过订单id查询订单
        OrderInfo orderInfo = orderService.selectOrderByOrderNo(orderNo);
        checkOrder(userInfo, orderInfo);
        orderInfo.setStatus(OrderStatus.preRefund);
        orderInfo.setExtraInfo(Utility.setExtraInfo(orderInfo.getExtraInfo(), "refund_reason", reason));
        Integer refundAmount = orderService.getRefundAmount(orderInfo);
        orderInfo.setSnapshotRefundFee(refundAmount);
        orderInfo.setExtraInfo(Utility.setExtraInfo(orderInfo.getExtraInfo(), "refund_fee", refundAmount));
        Integer res = orderService.updateByPrimaryKey(orderInfo);
        if (res != 1) {
            throw new ServiceException("修改订单状态为待退款失败");
        }
        //发送通知
        refundSms(orderInfo);
        //推送订单退款通知
//        webSocket.sendMessage("客户发送退款申请，请前去处理");
        return ResponseEntity.ok(AjaxResponseBody.success());
    }

    private void refundSms(OrderInfo orderInfo) {
        try {
            RoomInfo roomInfo = roomInfoService.selectByPrimaryKey(orderInfo.getRoomId());
            if (roomInfo == null) {
                log.info("该订单对应房间不存在orderNo = {}", orderInfo.getOrderNo());
                throw new ServiceException("该订单对应房间不存在");
            }
            HotelInfo hotelInfo = hotelService.selectHotelInfoById(roomInfo.getHotelId());
            if (hotelInfo == null) {
                log.info("该订单对应酒店不存在orderNo = {}", orderInfo.getOrderNo());
                throw new ServiceException("该订单对应酒店不存在");
            }
            //用户退款给酒店发送短信，并推送消息
//        String phone = hotelService.getSmsPhoneByHotelInfo(hotelInfo);
            String phone = hotelInfo.getPhone();
            Map<String, String> map = orderService.getNameAndPhoneByOrderInfo(orderInfo);
            String person = map.get("name");
            String checkIn = DateUtils.toYYMMddStr(orderInfo.getCheckIn());
            String checkOut = DateUtils.toYYMMddStr(orderInfo.getCheckOut());
            String hotelName = hotelInfo.getName();
            String roomtype = roomInfo.getTitle();
            Integer count = DateUtils.getDayByBeginEnd(orderInfo.getCheckIn(), orderInfo.getCheckOut()).intValue();
            smsService.sendSmsForUserRefund(phone, person, checkIn, hotelName, roomtype);
            //将用户发起退款申请记录写入表中
            Map<String, String> param = templateService.orderAfterHandleValue(MessageTemplate.ORDER_USER_REFUND, hotelName, checkIn, checkOut, count);
            noticeService.createNoticeAndSave(param, orderInfo.getUserId(), hotelInfo.getId());
        } catch (Exception e) {
            log.error("用户发起退款请求异常{}", e.getLocalizedMessage());
            e.printStackTrace();
        }
    }

    /**
     * 获取用户应该退款的金额
     *
     * @return
     */
    @ApiOperation(value = "获取用户应该退款的金额", notes = "获取用户应该退款的金额")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "orderNo", value = "订单号", required = true, dataType = "String")
    })
    @RequestMapping(value = "/refundAmount", method = RequestMethod.POST)
    public ResponseEntity<?> refundAmount(@RequestParam(name = "token") String token,
                                          @RequestParam(name = "orderNo") String orderNo) {
        log.info("参数token和orderNo{}{}", token, orderNo);
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        //通过订单id查询订单
        OrderInfo orderInfo = orderService.selectOrderByOrderNo(orderNo);
        checkOrder(userInfo, orderInfo);
        Integer refundAmount = orderService.getRefundAmount(orderInfo);
        Map<String, Integer> map = new HashMap<>();
        map.put("refundAmount", refundAmount);
        map.put("totalFee", orderInfo.getSnapshotTotalFee());
        return ResponseEntity.ok(AjaxResponseBody.success(map));
    }

    /**
     * 获取退款说明和退款原因
     *
     * @return
     */
    @ApiOperation(value = "获取退款说明和退款原因", notes = "获取退款说明和退款原因")
    @RequestMapping(value = "/refund/desc", method = RequestMethod.POST)
    public ResponseEntity<?> refundDesc() {
        String desc = configService.getValue(ConfigKey.REFUND_EXPLAIN);
        String reason = configService.getValue(ConfigKey.REFUND_REASON);
        Map<String, List<String>> map = new HashMap<>();
        map.put("desc", Splitters.splitToString(desc, Splitters.COMMA));
        map.put("reason", Splitters.splitToString(reason, Splitters.COMMA));
        return ResponseEntity.ok(AjaxResponseBody.success(map));
    }

    /**
     * 用户给酒店评分
     *
     * @param token
     * @param orderNo
     * @param score
     * @return
     */
    @ApiOperation(value = "用户给酒店评分", notes = "用户给酒店评分")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "orderNo", value = "订单号", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "score", value = "评分", required = true, dataType = "int")
    })
    @RequestMapping(value = "/evaluate", method = RequestMethod.POST)
    public ResponseEntity<?> orderEvaluate(@RequestParam(name = "token") String token,
                                           @RequestParam(name = "orderNo") String orderNo,
                                           @RequestParam(name = "score", defaultValue = "100") Integer score) {
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        OrderInfo orderInfo = orderService.selectOrderByOrderNo(orderNo);
        if (orderInfo == null) {
            log.info("该订单不存在orderNo = {}", orderNo);
            throw new ServiceException("该订单不存在");
        }
        if (!orderInfo.getUserId().equals(userInfo.getId())) {
            throw new ServiceException("非本人订单不能操作");
        }
        if (!orderInfo.getStatus().equals(OrderStatus.postCheckOut)) {
            throw new ServiceException("非完成订单不能评价");
        }
        int rec = orderService.updateScoreAndStatusByOrderNo(orderNo, score, OrderStatus.comment);
        if (rec != 1) {
            throw new ServiceException("用户评分更新失败");
        }
        Integer hotelId = orderService.getHotelIdByOrderNo(orderNo);
        if (hotelId == null || hotelId == 0) {
            throw new ServiceException("该订单对应酒店不存在");
        }
        rec = hotelService.updateScore(hotelId);
        if (rec == 0) {
            throw new ServiceException("更新酒店评分失败");
        }
        //评论成功返鱼丸
        fishBallService.addFishBall(FormatUtils.fen2YuanInt(orderInfo.getSnapshotTotalFee()), orderInfo.getUserId(), 1, FishBallEnum.COMMIT.desc());
        return ResponseEntity.ok(AjaxResponseBody.success());
    }

    /**
     * 通过订单号查询该订单是否付款成功
     *
     * @param orderNo 订单号
     * @return
     */
    @ApiOperation(value = "通过订单号查询该订单是否付款成功", notes = "body中返回true或false")
    @ApiImplicitParam(paramType = "query", name = "orderNo", value = "订单号", required = true, dataType = "String")
    @RequestMapping(value = "/order/success", method = RequestMethod.POST)
    public ResponseEntity<?> orderSuccess(@RequestParam(name = "orderNo") String orderNo) {
        checkParamOrderNo(orderNo);
        Boolean flag = false;
        OrderInfo orderInfo = orderService.selectOrderByOrderNo(orderNo);
        if (orderInfo != null) {
            if (orderInfo.getStatus().equals(OrderStatus.preCheckIn)
                    || orderInfo.getStatus().equals(OrderStatus.living)) {
                flag = true;
            }
        }
        if (!flag) {
            VipOrder vipOrder = vipOrderService.selectOrderByOrderNo(orderNo);
            if (vipOrder != null) {
                if (vipOrder.getStatus().equals(VipOrderStatus.postPay)) {
                    flag = true;
                }
            }

        }
        return ResponseEntity.ok(AjaxResponseBody.success(flag));
    }

    /**
     * 订单详情
     *
     * @param orderNo 订单号
     * @return
     */
    @ApiOperation(value = "订单详情", notes = "订单详情", response = OrderDetailDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "orderNo", value = "订单号", required = true, dataType = "String")
    })
    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    public ResponseEntity<?> detail(@RequestParam(name = "token") String token,
                                    @RequestParam(name = "orderNo") String orderNo) {
        checkParamOrderNo(orderNo);
        OrderInfo orderInfo = orderService.selectOrderByOrderNo(orderNo);
        if (orderInfo == null) {
            log.info("该订单不存在orderNo = {}", orderNo);
            throw new ServiceException("该订单不存在");
        }
        UserInfo userInfo = userInfoService.tokenUserInfo(token);
        if (!userInfo.getId().equals(orderInfo.getUserId())) {
            throw new ServiceException("非本人订单，拒绝操作");
        }
        OrderDetailDTO detail = orderService.detail(orderInfo);
        return ResponseEntity.ok(AjaxResponseBody.success(detail));
    }

    private void checkOrder(UserInfo userInfo, OrderInfo orderInfo) {
        if (orderInfo == null) {
            throw new ServiceException("该订单不存在");
        }
        if (!userInfo.getId().equals(orderInfo.getUserId())) {
            throw new ServiceException("非本人订单");
        }
        if (!orderInfo.getStatus().equals(OrderStatus.preCheckIn)) {
            throw new ServiceException("该订单非待入住状态");
        }
    }

    private String alwayGetOpenid(String code, Boolean flag) {
        //公众号
        if (flag) {
            String gzhOpenId = null;
            try {
                MyConfig config = new MyConfig();
                Utility.switchConfig(true, null, config);
                JSONObject jsonObjectv2 = payService.wxParseCode(true, code, config);
                gzhOpenId = jsonObjectv2.get("openid").toString();
            } catch (Throwable e) {
                log.info("获取xcxOpenId失败{}", code);
                throw new ServiceException("获取公众号OpenId失败");
            }
            if (!Arguments.notEmpty(gzhOpenId)) {
                throw new ServiceException("获取公众号OpenId为空");
            }
            return gzhOpenId;
        }
        String xcxOpenId = null;
        try {
            MyConfig config = new MyConfig();
            Utility.switchConfig(flag, null, config);
            JSONObject jsonObjectv2 = payService.wxParseCode(flag, code, config);
            xcxOpenId = jsonObjectv2.get("openid").toString();
        } catch (Throwable e) {
            log.info("获取xcxOpenId失败{}", code);
            throw new ServiceException("获取小程序OpenId失败");
        }
        if (!Arguments.notEmpty(xcxOpenId)) {
            throw new ServiceException("获取小程序OpenId为空");
        }
        return xcxOpenId;
    }

    private String checkOpenid(UserInfo userInfo, String code, Boolean flag) {
        JSONObject jsonObject = JSONObject.parseObject(userInfo.getExtraInfo());
        //公众号
        if (flag) {
            String gzhOpenId = null;
            if (jsonObject != null) {
                gzhOpenId = (String) jsonObject.get("gzhOpenId");
            }
            if (gzhOpenId != null) {
                return gzhOpenId;
            }
            if (!Arguments.notEmpty(code)) {
                throw new ServiceException("openid为空");
            }
            try {
                MyConfig config = new MyConfig();
                Utility.switchConfig(true, null, config);
                JSONObject jsonObjectv2 = payService.wxParseCode(true, code, config);
                gzhOpenId = jsonObjectv2.get("openid").toString();
            } catch (Throwable e) {
                log.info("获取xcxOpenId失败{}", code);
                throw new ServiceException("获取公众号OpenId失败");
            }
            Map<String, Object> map = new HashMap<>();
            map.put("gzhOpenId", gzhOpenId);
            if (jsonObject != null) {
                String xcxOpenId = (String) jsonObject.get("xcxOpenId");
                if (Arguments.notEmpty(xcxOpenId)) {
                    map.put("xcxOpenId", xcxOpenId);
                }
            }
            userInfo.setExtraInfo(JSONObject.toJSONString(map));
            Integer res = userInfoService.updateExtraInfoById(userInfo.getId(), userInfo.getExtraInfo());
            if (res != 1) {
                throw new ServiceException("更新openid失败");
            }
            return gzhOpenId;
        }
        String xcxOpenId = null;
        if (jsonObject != null) {
            xcxOpenId = (String) jsonObject.get("xcxOpenId");
        }
        if (xcxOpenId != null) {
            return xcxOpenId;
        }
        if (!Arguments.notEmpty(code)) {
            throw new ServiceException("openid为空");
        }
        try {
            MyConfig config = new MyConfig();
            Utility.switchConfig(flag, null, config);
            JSONObject jsonObjectv2 = payService.wxParseCode(flag, code, config);
            xcxOpenId = jsonObjectv2.get("openid").toString();
        } catch (Throwable e) {
            log.info("获取xcxOpenId失败{}", code);
            throw new ServiceException("获取小程序OpenId失败");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("xcxOpenId", xcxOpenId);
        if (jsonObject != null) {
            String gzhOpenId = (String) jsonObject.get("gzhOpenId");
            if (Arguments.notEmpty(gzhOpenId)) {
                map.put("gzhOpenId", gzhOpenId);
            }
        }
        userInfo.setExtraInfo(JSONObject.toJSONString(map));
        Integer res = userInfoService.updateExtraInfoById(userInfo.getId(), userInfo.getExtraInfo());
        if (res != 1) {
            throw new ServiceException("更新openid失败");
        }
        return xcxOpenId;
    }

    private void checkParamOrderNo(String orderNo) {
        if (Arguments.isEmpty(orderNo)) {
            throw new ServiceException("订单号不能为空");
        }
    }

    private OrderInfo getOrderInfo(String name, String phone) {
        if (!Arguments.notEmpty(name)) {
            throw new ServiceException("用户真实姓名不能为空");
        }
        name = name.replaceAll("\\n", "");
        name = name.replaceAll("\\s", "");
        if (!Arguments.notEmpty(name)) {
            throw new ServiceException("用户真实姓名不能为空");
        }
        if (!Arguments.notEmpty(phone)) {
            throw new ServiceException("用户手机号不能为空");
        }
        if (!TextValidator.MOBILE.boolCheck(phone)) {
            throw new ServiceException("手机号格式不正确");
        }
        OrderInfo orderInfo = new OrderInfo();
        Map<String, String> map = new HashMap<>();
        map.put("name", name);
        map.put("phone", phone);
        orderInfo.setVitalPersonInfo(JSONObject.toJSON(map).toString());
        return orderInfo;
    }
}
